package gizwits.kit.byteutil;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;



/**
 * 字节操作工具类
 * @author CHND
 *
 */
public class ByteKit {
	
	private static Map<Integer,Integer> map;
	
	static{
		map = new HashMap<Integer, Integer>();
		map.put(0, 0x00);
		map.put(1, 0x01);
		map.put(2, 0x03);
		map.put(3, 0x07);
		map.put(4, 0x0f);
		map.put(5, 0x1f);
		map.put(6, 0x3f);
		map.put(7, 0x7f);
		map.put(8, 0xff);
	}
	
	/**
	 * 【整数】转【二进制字符串】
	 */
	public static String toBinaryStr(int source, int len){
		String str = Integer.toBinaryString(source);
		str = zero(str, len, '0');
		return str.substring(str.length()-len);
	}
	
	
	
	
	/**
	 * 【整数】转【十六进制字符串】
	 */
	public static String toHexStr(int source, int len){
		String str = Integer.toHexString(source);
		str = zero(str, len, '0');
		return str.substring(str.length()-len);
	}
	
	/**
	 * 用一串【十六进制字符串】转【字节数组】
	 */
	public static byte[] HexStrToBytes(String str, String split){
		String[] hex = str.split(split);
		byte[] bs = new byte[hex.length];
		int len = 0;
		for(String s : hex){
			bs[len++] = (byte)Integer.parseInt(s,16);
		}
		return bs;
	}
	
	
	
	/**
	 * 补字符的方法
	 * @param str 原字符串
	 * @param len 补完后的长度
	 * @param o 补的字符
	 * @return
	 */
	public static String zero(String str, int len, char o){
		len = len - str.length();
		StringBuffer buffer = new StringBuffer();
		while(len>0){
			buffer.append(o);
			--len;
		}
		buffer.append(str);
		return buffer.toString();
	}
	
	
	
	/**
	 * 8位【二进制数字符串】转【字节】
	 */
	public static byte toBinary(String byteStr) {
	    int re, len;  
	    if (null == byteStr) {  
	        return 0;  
	    }  
	    len = byteStr.length();  
	    if (0>=len || len>8) {  
	        return 0;  
	    }  
        if (byteStr.charAt(0) == '0') {// 正数  
            re = Integer.parseInt(byteStr, 2);  
        } else {// 负数  
            re = Integer.parseInt(byteStr, 2) - 256;  
        }  
	    return (byte) re;
	}
	
	/**
	 * 【大端模式】【二进制字符串】转【字节数组】
	 */
	public static byte[] toBinarysOfBig(String byteStr){
		if((byteStr.length() % 8)!=0)return null;
		int len = byteStr.length()/8;
		byte[] result = new byte[len];
		for(int i=0;i<len;i++){
			result[i] = toBinary(byteStr.substring(i*8,(i*8)+8));
		}
		return result;
	}
	
	/**
	 * 【小端模式】【二进制字符串】转【字节数组】
	 */
	public static byte[] toBinarysOfLittle(String byteStr){
		if((byteStr.length() % 8)!=0)return null;
		int len = byteStr.length()/8;
		byte[] result = new byte[len];
		for(int i=0;i<len;i++){
			result[len-1-i] = toBinary(byteStr.substring(i*8,(i*8)+8));
		}
		return result;
	}
	
	/**
	 * 【数字】转【字节数组】
	 * @param num
	 * @param len
	 * @param isBig 是否为大端模式
	 * @return
	 */
	public static byte[] toByte(long num,int len, boolean isBig){
		return isBig ? toByteOfBig(num, len) : toByteOfLittle(num, len);
	}
	
	/**
	 * 【小端格式】【数字】转【字节数组】
	 */
	public static byte[] toByteOfLittle(long num,int len){
		byte[] bs = new byte[len];
		for(int i=0;i<len;i++){
			bs[i] = (byte)(0xff & (num >> (i*8)));
		}
		return bs;
	}
	
	
	/**
	 * 【大端格式】【数字】转【字节数组】
	 */
	public static byte[] toByteOfBig(long num,int len){
		byte[] bs = new byte[len];
		for(int i=0;i<len;i++){
			bs[i] = (byte)(0xff & (num >> ((len-1-i)*8)));
		}
		return bs;
	}
	
	/**
	 * 截取字节数组
	 * @param bs
	 * @param start
	 * @param len
	 * @param isBig 是否以大端格式输出
	 * @return
	 */
	public static byte[] toByte(byte[] bs, int start, int len, boolean isBig){
		byte[] resultBytes = new byte[len];
		for(int i=0;i<len;i++){
			resultBytes[isBig?i:len-1-i] = bs[start+i];
		}
		return resultBytes;
	}
	
	/**
	 * 【正常模式】字节数组转long
	 * @param bs
	 * @return
	 */
	public static long toLong(byte[] bs,boolean isBig){
		return isBig ? toLongOfBig(bs, 0, bs.length) : toLongOfLittle(bs, 0, bs.length);
	}
	
	
	/**
	 * 【小端格式的字节数组】转【数字】
	 */
	public static long toLongOfLittle(byte[] bs,int start,int len){
		long num = 0;
		for(int i=0;i<len;i++){
			num = num | ((bs[i+start] & 0xff) << i * 8);
		}
	    return num;  
	}
	
	
	/**
	 * 【大端格式的字节数组】转【数字】
	 * @param bs
	 * @param start
	 * @param len
	 * @return
	 */
	public static long toLongOfBig(byte[] bs,int start,int len){
		long num = 0;
		for(int i=0;i<len;i++){
			num = num | (((long)(bs[i+start] & 0xff)) << (len-1-i) * 8);
		}
	    return num;  
	}
	
	
	
	/**
	 * 把【一个字节中的几个bit】转【整数】
	 * @param b
	 * @param index
	 * @param len
	 * @param isLeft true为从左开始
	 * @return
	 */
	public static int toInt(byte b, int index, int len, boolean isLeft){
		return isLeft ? toIntByLeft(b, index, len) : toIntByRight(b, index, len);
	}
	
	/**
	 * 把【一个字节中的几个bit】转【整数】,从右开始
	 */
	public static int toIntByRight(byte b, int index, int len) {
		return (b>>index)&map.get(len);
	}
	
	/**
	 * 把【一个字节中的几个bit】转【整数】,从左开始
	 */
	public static int toIntByLeft(byte b, int index, int len) {
		return (b>>(8-(index+len)))&map.get(len);
	}
	
	/**
	 * 把所有【字节数组】合并;【计算【所有字节数组的总长度】并添加到【结果数组的头部】】长度格式【两个字节】
	 * @param isBig 总长度的模式,true为大端，false为小端
	 * @param arrays 字节数组
	 * @return
	 */
	public static byte[] toResult(boolean isBig, byte[]... arrays){
		int len = 2;	//len的长度为2
		for(byte[] array : arrays){
			len += array.length;
		}
		byte[] first = isBig?toByteOfBig(len,2):toByteOfBig(len,2);
		byte[] result = concatAll(first,arrays);
		return result;
	}
	
	/**
	 * 合并【字节数组】【纯合并】first+arrays...
	 * @param first 
	 * @param rest
	 * @return
	 */
	public static byte[] concatAll(byte[] first, byte[]... arrays) {
		  int totalLength = first.length;  
		  for (byte[] array : arrays) {  
		    totalLength += array.length;  
		  }  
		  byte[] result = Arrays.copyOf(first, totalLength);
		  int offset = first.length;  
		  for (byte[] array : arrays) {  
		    System.arraycopy(array, 0, result, offset, array.length);  
		    offset += array.length;  
		  }  
		  return result;  
	} 
	
	
	/**
	 * 打印【字节数组】
	 */
	public static void printBytes(byte[] array){
		if(array==null){log("字节数组 - 空");return;}
		int id = 1;
		String ten = "";
		String hex = "";
		String two = "";
		for(byte b : array){
			ten += "("+id+++")"+b+" ";
			hex += toHexStr(b, 2)+" ";
			two += toBinaryStr(b, 8)+" ";
		}
		log("十进制:"+ten);
		log("十六进制:"+hex);
		log("二进制:"+two);
		log("字节长度:"+array.length);
	}
	
	/**
	 * 打印【字节数组】,带标题
	 */
	public static void printBytes(String title, byte[] array){
		log("");
		log(title);
		printBytes(array);
		log("");
	}
	
	/**
	 * 输出指针
	 * @param obj
	 */
	private static void log(Object obj){
		System.out.println(obj);
	}
	
	public static boolean isBlank(byte[] array){
		return (array==null || array.length==0) ? true : false;
	}
	
	public static boolean notBlank(byte[] array){
		return !isBlank(array);
	}
}
